home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Libraries / MCC Utils / MCStrings.p < prev    next >
Encoding:
Text File  |  1994-05-04  |  13.9 KB  |  464 lines  |  [TEXT/PJMM]

  1. {This document is formated in monaco 9 pt                                          }
  2. {                                                                                  }
  3. {LEGAL STUFF                                                                       }
  4. {                                                                                  }
  5. {Copyright © 1994 by University of Melbourne. All Rights Reserved. This work is    }
  6. {provided "as is" and without any express or implied warranties, including,        }
  7. {without limitation, the implied warranties of merchantability and fitness         }
  8. {for a particular purpose.                                                         }
  9. {                                                                                  }
  10. {University of Melbourne is not responsible for the consequences of the use of this}
  11. {work, regardless of the cause. You may use this work in a public domain,          }
  12. {freeware, or shareware product with no restrictions, as long as you include       }
  13. {the following notice in your product's about box or splash screen:                }
  14. {  "Portions Copyright © 1994 by University of Melbourne".                         }
  15. {If you use more than 50 lines of this work, please credit the author also:        }
  16. {  "Portions by Michael Cutter"                                                    }
  17. {Public domain is defined as something that you release to the public, without     }
  18. {copyright and without restrictions on use. Freeware is a copyrighted work,        }
  19. {for which you charge no money. Shareware is a copyrighted work for which you      }
  20. {charge a fee if the user decides to keep it. If you intend to use this work       }
  21. {in a commercial product, please contact us.                                       }
  22. {                                                                                  }
  23. {                                                                                  }
  24. {OTHER STUFF                                                                       }
  25. {                                                                                  }
  26. {AUTHOR:                                                                           }
  27. { Michael Trevor Cutter                                                            }
  28. {                                                                                  }
  29. {CONTACT:                                                                          }
  30. {  Internet:                                                                       }
  31. {    mtc@arbld.unimelb.edu.au (Preferred)                                          }
  32. {  Snail Mail:                                                                     }
  33. {    Dept of Architecture & Building                                               }
  34. {    University of Melbourne                                                       }
  35. {    Parkville VIC 3052                                                            }
  36. {    AUSTRALIA                                                                     }
  37. {                                                                                  }
  38. {PERSONAL STUFF                                                                    }
  39. {  I'd really appreciate it if you'd let me know what you're using my code         }
  40. {  in, (send me email or a postcard). Please report any bugs or errors to me.      }
  41. {                                                                                  }
  42. {MODULE DESCRIPTION                                                                }
  43. {This modules includes a variety of functions for manipulating string resources,   }
  44. {include settings STR# resources.                                                  }
  45.  
  46. unit MCStrings;
  47. interface
  48.     uses
  49.         MCHandlesAndStrs;
  50.     type
  51.         MCParamStrArray = array[0..9] of Str255;
  52.  
  53. {This is just my own ParamStr function. Handles ^0..^9, rather than just ^0..^3 like the dialog}
  54. {manager one does.}
  55.     procedure MCParamStr (var deststr: Str255;
  56.                                     strs: MCParamStrArray);
  57.  
  58. {given outstr, insert instr into outstr where the ^0 is. Doesn't handle multiple occurrences of ^0}
  59.     procedure MCInsertString (instr: str255;
  60.                                     var outstr: str255);
  61.  
  62. {My interface to GetString, cause I like it better this way}
  63. {not very stack friendly, tho}
  64.     function MCGetString (resid: integer): str255;
  65.  
  66. {Loads the STR resource called strname}
  67.     function MCGetNamedString (strname: Str255): str255;
  68.  
  69. {Get the STR resource with id resid, and insert instr at the first occurrence of ^0 in it}
  70.     function MCGetInsertionString (resid: integer;
  71.                                     instr: str255): str255;
  72.  
  73. {Get the STR# resource with id resid, and the index'th string in it}
  74.     function MCGetIndString (resid: integer;
  75.                                     index: integer): str255;
  76.  
  77. {Count the number of strings in a STR# resource resid}
  78.     function MCCountIndStrings (resid: integer;
  79.                                     var numofstrs: integer): OSErr;
  80.  
  81. {Get the STR# resource with id resid, and the index'th string in it}
  82. {and insert instr at the first occurrence of ^0}
  83.     function MCGetIndInsertionString (resid: integer;
  84.                                     index: integer;
  85.                                     instr: str255): str255;
  86.  
  87. {VERY simple encryption function (it actually just does a rot-13. Do NOT use}
  88. {except where you don't REALLY mind it being hacked}
  89.     function MCEncryptString (str: str255): str255;
  90.     function MCUnencryptString (str: str255): str255;
  91.     function MCGetEncryptedString (resid: integer): str255;
  92.  
  93. {Set the STR resource to newstr}
  94.     function MCSetString (resid: integer;
  95.                                     newstr: str255): OSErr;
  96. {Set the index'th string of the STR# resource to newstr}
  97.     function MCSetIndString (resid: integer;
  98.                                     index: integer;
  99.                                     newstr: str255): OSErr;
  100. implementation
  101.  
  102.     procedure MCParamStr (var deststr: Str255;
  103.                                     strs: MCParamStrArray);
  104. {allows you to insert up to 10 parameters into a string, rather than the limit of four which ParamStr gives you}
  105.         var
  106.             i, off: integer;
  107.             numstr: Str255;
  108.     begin
  109.         i := 0;
  110.         while (strs[i] <> '') and (i <= 9) do
  111.             begin
  112.                 numstr := '';
  113.                 NumToString(i, numstr);
  114.                 numstr := concat('^', numstr);
  115.                 off := 0;
  116.                 off := pos(numstr, deststr);
  117.                 if off <> 0 then
  118.                     begin
  119.                         delete(deststr, off, 2);
  120.                         insert(strs[i], deststr, off);
  121.                     end;
  122.                 i := i + 1;
  123.             end;
  124.     end;
  125.  
  126.     procedure MCInsertString (instr: str255;
  127.                                     var outstr: str255);
  128. {searches given string for ^0, and replaces it with instr}
  129.         var
  130.             off: integer;
  131.     begin
  132.         off := pos('^0', outstr);
  133.         if off <> 0 then
  134.             begin
  135.                 delete(outstr, off, 2);
  136.                 insert(instr, outstr, off);
  137.             end;
  138.     end;
  139.  
  140.     function MCGetString;
  141.         var
  142.             strh: StringHandle;
  143.     begin
  144.         strh := nil;
  145.         strh := StringHandle(NewHandle(0));
  146.         strh := GetString(resid);
  147.         if (strh <> nil) and (GetHandleSize(Handle(strh)) > 0) then
  148.             begin
  149.                 hlock(handle(strh));
  150.                 MCGetString := strh^^;
  151.                 hunlock(handle(strh));
  152.                 ReleaseResource(handle(strh));
  153.             end
  154.         else
  155.             MCGetString := '';
  156.     end;
  157.  
  158.     function MCGetNamedString;
  159.         var
  160.             strh: StringHandle;
  161.     begin
  162.         strh := nil;
  163.         strh := StringHandle(Get1NamedResource('STR ', strname));
  164.         if (strh <> nil) and (GetHandleSize(Handle(strh)) > 0) then
  165.             begin
  166.                 hlock(handle(strh));
  167.                 MCGetNamedString := strh^^;
  168.                 hunlock(handle(strh));
  169.                 ReleaseResource(handle(strh));
  170.             end
  171.         else
  172.             MCGetNamedString := '';
  173.     end;
  174.  
  175.     function MCGetInsertionString;
  176.         var
  177.             str: str255;
  178.             strh: StringHandle;
  179.     begin
  180.         strh := StringHandle(NewHandle(0));
  181.         strh := GetString(resid);
  182.         if (strh <> nil) and (GetHandleSize(Handle(strh)) > 0) then
  183.             begin
  184.                 DetachResource(handle(strh));
  185.                 hlock(handle(strh));
  186.                 str := strh^^;
  187.                 MCInsertString(instr, str);
  188.                 MCGetInsertionString := str;
  189.                 hunlock(handle(strh));
  190.                 ReleaseResource(handle(strh));
  191.             end
  192.         else
  193.             MCGetInsertionString := '';
  194.     end;
  195.  
  196.     function MCGetIndString;
  197.     begin
  198.         GetIndString(MCGetIndString, resid, index);
  199.     end;
  200.  
  201.     function MCCountIndStrings;
  202.         var
  203.             resh: Handle;
  204.             myErr: OSErr;
  205.     begin
  206.         MCCountIndStrings := noErr;
  207.         resh := nil;
  208.         resh := Get1Resource('STR#', resid);
  209.         if resh <> nil then
  210.             begin
  211.                 hlock(resh);
  212.                 BlockMove(resh^, @numofstrs, 2);
  213.                 hunlock(resh);
  214.                 ReleaseResource(resh);
  215.             end
  216.         else
  217.             begin
  218.                 MCCountIndStrings := ResError;
  219.             end;
  220.     end;
  221.  
  222.     function MCGetIndInsertionString;
  223.         var
  224.             str: str255;
  225.     begin
  226.         GetIndString(str, resid, index);
  227.         MCInsertString(instr, str);
  228.         MCGetIndInsertionString := str;
  229.     end;
  230.  
  231.  
  232.     function MCEncryptString (str: str255): str255;
  233. {ASK MIKE!!!! Are ~'s allowed in Passwords?}
  234.         var
  235.             pos, i, len: integer;
  236.             c, e: char;
  237.             kspace, ktilde: integer; {start and end of printable ascii}
  238.     begin
  239. {init}
  240.         kspace := ord(' ');
  241.         ktilde := ord('~');
  242.  
  243.         len := length(str);
  244.         for i := 1 to len do
  245.             begin
  246.                 c := str[i];
  247.                 pos := ord(c) + 13;
  248.                 if pos > ktilde then
  249.                     str[i] := chr(pos - ktilde + kspace) {over end of 'alphabet'}
  250.                 else
  251.                     str[i] := chr(pos);    {not over end of 'alphabet'}
  252.             end;
  253.         MCEncryptString := str;
  254.     end;
  255.  
  256.     function MCUnencryptString (str: str255): str255;
  257.         var
  258.             pos, i, len: integer;
  259.             c, e: char;
  260.             kspace, ktilde: integer; {start and end of printable ascii}
  261.     begin
  262. {init}
  263.         kspace := ord(' ');
  264.         ktilde := ord('~');
  265.  
  266.         len := length(str);
  267.         for i := 1 to len do
  268.             begin
  269.                 c := str[i];
  270.                 pos := ord(c) - 13;
  271.                 if pos < kspace then
  272.                     str[i] := chr(ktilde - (kspace - pos)) {over start of 'alphabet'}
  273.                 else
  274.                     str[i] := chr(pos);    {not over start of 'alphabet'}
  275.             end;
  276.         MCUnencryptString := str;
  277.     end;
  278.  
  279.     function MCGetEncryptedString;
  280. {This function currently decodes a simple Rot-13 encryption method}
  281.         var
  282.             encstr: str255;
  283.             strh: StringHandle;
  284.     begin
  285.         strh := StringHandle(NewHandle(0));
  286.         strh := GetString(resid);
  287.         if strh <> nil then
  288.             begin
  289.                 DetachResource(handle(strh));
  290.                 hlock(handle(strh));
  291.                 encstr := strh^^;
  292.                 hunlock(handle(strh));
  293.                 ReleaseResource(handle(strh));
  294.                 encstr := MCUnencryptString(encstr);
  295.             end
  296.         else
  297.             encstr := '';
  298.         MCGetEncryptedString := encstr;
  299.     end;
  300.  
  301.     function MCSetString (resid: integer;
  302.                                     newstr: str255): OSErr;
  303.         var
  304.             tmpstrh: StringHandle;
  305.     begin
  306.         MCSetString := noErr;
  307.         tmpstrh := nil;
  308.         tmpstrh := StringHandle(Get1Resource('STR ', resid));
  309.         if ResError <> noErr then
  310.             begin
  311.                 MCSetString := ResError;
  312.                 exit(MCSetString);
  313.             end;
  314.         SetString(tmpstrh, newstr);
  315.         ChangedResource(handle(tmpstrh));
  316.         if ResError <> noErr then
  317.             begin
  318.                 MCSetString := ResError;
  319.                 exit(MCSetString);
  320.             end;
  321.         WriteResource(handle(tmpstrh));
  322.         if ResError <> noErr then
  323.             begin
  324.                 MCSetString := ResError;
  325.                 exit(MCSetString);
  326.             end;
  327.         ReleaseResource(handle(tmpstrh));
  328.     end;
  329.  
  330.     function MCSetIndString (resid: integer;
  331.                                     index: integer;
  332.                                     newstr: str255): OSErr;
  333. {how this works: }
  334. {Load resource into memory}
  335. {get the number of strs in the resource}
  336. {index your way to the start of the requested str}
  337. {remember that position, then move along to start of next str}
  338. {copy remainder of the handle into new handle}
  339. {delete everything in the original handle past the start of the desired str}
  340. {append the new str onto the original handle}
  341. {append the remaining handle on to the handle}
  342. {dispose any handles}
  343. {save the resource}
  344. {exit}
  345.  
  346.         var
  347.             resh, remh, beginh: Handle;
  348.             numofstrs: integer;
  349.             strstart, nextstrstart: longint;
  350.  
  351.             curpos, reshandlesize: longint;
  352.             curstr, strlen: integer;
  353.  
  354.         procedure CatchOSErr (err: OSErr);
  355.         begin
  356.             if err <> noErr then
  357.                 begin
  358.                     MCSetIndString := err;
  359.                     exit(MCSetIndString)
  360.                 end;
  361.         end;
  362.     begin
  363.         MCSetIndString := noErr;
  364.  
  365. {Load resource into memory}
  366.         resh := nil;
  367.         resh := Get1Resource('STR#', resid);
  368.         CatchOSErr(ResError);
  369.         reshandlesize := GetHandleSize(resh);
  370.         Hlock(resh);
  371.  
  372. {get the number of strs in the resource}
  373.         BlockMove(resh^, @numofstrs, 2);
  374.         CatchOSErr(MemError);
  375.  
  376. {index your way to the start of the requested str}
  377.     {get length of first string}
  378.         curpos := 2;
  379.         curstr := 1;
  380.         if index = 2 then
  381.             begin
  382.                 strlen := 0;
  383.                 BlockMove(pointer(ord4(resh^) + curpos), pointer(ord4(@strlen) + 1), 1);
  384.                 CatchOSErr(MemError);
  385.                 curpos := curpos + strlen + 1; {the 1 is for the length byte}
  386.             end
  387.         else if index > 2 then
  388.             begin
  389.                 repeat
  390.                     strlen := 0;
  391.                     BlockMove(pointer(ord4(resh^) + curpos), pointer(ord4(@strlen) + 1), 1);
  392.                     CatchOSErr(MemError);
  393.                     curpos := curpos + strlen + 1; {the 1 is for the length byte}
  394.                     curstr := curstr + 1;
  395.                 until (curpos > reshandlesize) or (curstr = index);
  396.                 if curpos > reshandlesize then
  397.                     CatchOSErr(10000 + index);
  398.             end;
  399.         strstart := curpos;
  400.  
  401. {remember that position, then move along to start of next str}
  402.         strlen := 0;
  403.         BlockMove(pointer(ord4(resh^) + curpos), pointer(ord4(@strlen) + 1), 1);
  404.         CatchOSErr(MemError);
  405.  
  406.         curpos := curpos + strlen + 1;
  407.         nextstrstart := curpos;
  408.  
  409. {copy remainder of the handle into new handle}
  410.         remh := nil;
  411.         remh := NewHandle(reshandlesize - nextstrstart);
  412.         hlock(remh);
  413.         BlockMove(pointer(ord4(resh^) + nextstrstart), remh^, reshandlesize - nextstrstart);
  414.         CatchOSErr(MemError);
  415.         hunlock(remh);
  416.  
  417. {delete everything in the original handle past the start of the desired str}
  418.     {copy up to start of string}
  419.         beginh := nil;
  420.         beginh := NewHandle(strstart);
  421.         hlock(beginh);
  422.         BlockMove(resh^, beginh^, strstart);
  423.         CatchOSErr(MemError);
  424.  
  425.         hunlock(beginh);
  426.  
  427. {append the new str onto the original handle}
  428.         reshandlesize := GetHandleSize(beginh);
  429.         strlen := length(newstr);
  430.  
  431. {append length byte}
  432.         BlockMove(pointer(ord4(@strlen) + 1), pointer(ord4(beginh^) + reshandlesize), 1);
  433.         CatchOSErr(MemError);
  434.         SetHandleSize(beginh, reshandlesize + 1);
  435.         CatchOSErr(MCAppendStrToHndl(newstr, beginh));
  436.  
  437. {append the remaining handle on to the handle}
  438.         CatchOSErr(MCAppendHndlToHndl(remh, beginh));
  439.  
  440. {copy the new handle back to resh}
  441.         reshandlesize := GetHandleSize(beginh);
  442.         hlock(beginh);
  443.         hunlock(resh);
  444.         SetHandleSize(resh, reshandlesize);
  445.         hlock(resh);
  446.         BlockMove(beginh^, resh^, reshandlesize);
  447.         CatchOSErr(MemError);
  448.         hunlock(resh);
  449.         hunlock(beginh);
  450.  
  451. {dispose all internally allocated handles}
  452.         DisposeHandle(beginh);
  453.         DisposeHandle(remh);
  454.  
  455. {save the resource}
  456.         ChangedResource(resh);
  457.         CatchOSErr(ResError);
  458.  
  459.         WriteResource(resh);
  460.         CatchOSErr(ResError);
  461.         ReleaseResource(resh);
  462.     end;
  463.  
  464. end.